"""由打印的当前线程名称可以看出，两个coroutine是由同一个线程并发执行的。

如果把asyncio.sleep()换成真正的IO操作，则多个coroutine就可以由一个线程并发执行。"""
"""异步协程
python中使用协程最常用的库就是asyncio，首先先介绍几个概念：

1、event_loop 事件循环：相当于一个无限循环，我们可以把一些函数注册到这个事件循环上，当满足条件时，就会调用对应的处理方法。
2、coroutine 协程：协程对象，只一个使用async关键字定义的函数，他的调用不会立即执行函数，而是会返回一个协程对象。协程对象需要注册到事件循环中，由事件循环调用。
3、task 任务：一个协程对象就是一个原生可以挂起的函数，任务则是对协程的进一步封装，其中包含任务的各种状态。
4、future：代表将来执行或没有执行的任务结果。它与task没有本质的区别。
5、async/await 关键字：python3.5用于定义协程的关键字，async定义一个协程，await用于挂起阻塞的异步调用接口。
1、定义一个协程 通过async定义一个协程，协程是一个对象，不能直接运行，需要把协程加入到事件循环（loop）中，由loop在适当的时候调用协程。asyncio.get_event_loop()方法可以创建一个事件循环，然后由run_until_complete(协程对象)将协程注册到事件循环中，并启动事件循环。

run_until_complete根据传递的参数的不同，返回的结果也有所不同

1、run_until_complete()传递的是一个协程对象或task对象，则返回他们finished的返回结果（前提是他们得有return的结果，否则返回None）
2、run_until_complete(asyncio.wait(多个协程对象或任务))，函数会返回一个元组包括（done, pending），通过访问done里的task对象，获取返回值
3、run_until_complete(asyncio.gather(多个协程对象或任务))，函数会返回一个列表，列表里面包括各个任务的返回结果，按顺序排列
python 3.7 以前的版本调用异步函数的步骤：

1、调用asyncio.get_event_loop()函数获取事件循环loop对象
2、通过不同的策略调用loop.run_forever()方法或者loop.run_until_complete()方法执行异步函数
python3.7 以后的版本使用asyncio.run即可。此函数总是会创建一个新的事件循环并在结束时关闭之。它应当被用作 asyncio 程序的主入口点，理想情况下应当只被调用一次。
————————————————
版权声明：本文为CSDN博主「夜风晚凉」的原创文章，遵循CC 4.0 BY-SA版权协议，转载请附上原文出处链接及本声明。
原文链接：https://blog.csdn.net/weixin_41599977/article/details/93656042"""
import threading
import asyncio


@asyncio.coroutine
def hello():
    print('Hello world! (%s)' % threading.currentThread())
    yield from asyncio.sleep(1)
    print('Hello again! (%s)' % threading.currentThread())


loop = asyncio.get_event_loop()
tasks = [hello(), hello()]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
